package com.mkh.st.common.core.util;

import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

/**
 * Author: xhx
 * Date: 2021/10/15 8:53 下午
 * FileName: FreeMarkerUtils
 * Description: 模板管理器
 */
public class FreeMarkerUtils {
	private static FreeMarkerUtils instance = null;

	private Map<String, Object> toolMap = new HashMap<String, Object>();
	/** 文件模板配置 */
	private Configuration fileConfiguration;
	/** 文件路径 */
	private String templateDir = "/config/template";
	/** classpath路径 */
	private boolean isClassPath = true;
	/** 模板更新检查间隔时间（秒） */
	private Integer updateDelaySeconds;

	private FreeMarkerUtils() {
	}

	public static FreeMarkerUtils instance() {
		if (instance != null) {
			return instance;
		}
		synchronized (FreeMarkerUtils.class) {
			if (instance == null) {
				instance = new FreeMarkerUtils();
				instance.init();
			}
		}
		return instance;
	}

	public Configuration getConfiguration() {
		return this.fileConfiguration;
	}

	/**
	 * 取指定名称的模板
	 *
	 * @param fileName
	 *            模板文件名称
	 */
	protected Template getTemplate(String fileName) throws IOException {
		return fileConfiguration.getTemplate(fileName);

	}

	/**
	 * 模板存放路径
	 *
	 * @return
	 */
	public String getTemplateDir() {
		return templateDir;
	}

	public Map<String, Object> getToolMap() {
		return toolMap;
	}

	/**
	 * 模板更新检查间隔时间（秒）
	 *
	 * @return
	 */
	public Integer getUpdateDelaySeconds() {
		return updateDelaySeconds;
	}

	/**
	 * 模板初始化<br>
	 * 模板路径：指定的文件路径。
	 *
	 * @exception Exception
	 */
	public void init() {
		try {
			fileConfiguration = new freemarker.template.Configuration();
			fileConfiguration.setEncoding(java.util.Locale.CHINA, "UTF-8");

			// 从类路径中取模板
			if (isClassPath) {
				fileConfiguration.setClassForTemplateLoading(this.getClass(), getTemplateDir());
			} else {
				// 从文件系统中取模板
				fileConfiguration.setDirectoryForTemplateLoading(new File(getTemplateDir()));
			}
		} catch (Exception e) {
			System.out.println("初始化FreeMarker时异常");
			e.printStackTrace();
		}
		if (updateDelaySeconds == null) {
			// 每隔30分钟检查模版是否更新
			fileConfiguration.setTemplateUpdateDelay(1800);
		} else {
			fileConfiguration.setTemplateUpdateDelay(updateDelaySeconds.intValue());
		}
	}

	/**
	 * 根据模板文件内容创建报文.
	 *
	 * @param fileName
	 *            模板文件名
	 * @param dataMap
	 *            数据容器
	 * @exception Exception
	 */
	public String mergeFile(String fileName, Map<String, Object> dataMap) throws IOException, TemplateException {
		// 获取模板文件
		Template t = getTemplate(fileName);
		Writer out = new java.io.StringWriter();
		if (dataMap == null) {
			dataMap = new HashMap<String, Object>();
		}
		if (!toolMap.isEmpty()) {
			dataMap.putAll(toolMap);
		}
		t.process(dataMap, out);
		return out.toString();
	}

	/**
	 * 直接用传入的字符串模板合并文本。
	 *
	 * @param templateContent
	 *            模板内容
	 * @param dataMap
	 *            数据集合
	 * @return 合并后的文本
	 */
	public String mergeText(String templateContent, Map<String, Object> dataMap) {
		if (dataMap == null || dataMap.size() == 0) {
			return null;
		}

		if (!toolMap.isEmpty()) {
			dataMap.putAll(toolMap);
		}
		String templateKey = "KEY";
		Configuration cfg = new Configuration();
		StringTemplateLoader stringLoader = new StringTemplateLoader();
		stringLoader.putTemplate(templateKey, templateContent);
		cfg.setTemplateLoader(stringLoader);

		try {
			Template t2 = cfg.getTemplate(templateKey);
			Writer out = new java.io.StringWriter();
			t2.process(dataMap, out);
			return out.toString();
		} catch (freemarker.core.ParseException pe) {
			throw new RuntimeException("合并模板时发生解析异常", pe);
		} catch (Exception e) {
			System.out.println("合并模板时异常");
			e.printStackTrace();
			throw new RuntimeException("合并数据时发生错误:" + e.getMessage(), e);
		}
	}

	/**
	 * 用于标识是否从类路径中取模板。<br>
	 * 如果不设置此参数，系统默认true。
	 *
	 * @param isClassPath
	 */
	public void setIsClassPath(boolean isClassPath) {
		this.isClassPath = isClassPath;
	}

	/**
	 * 模板存放路径
	 *
	 * @return
	 */
	public void setTemplateDir(String templateDir) {
		this.templateDir = templateDir;
	}

	public void setToolMap(Map<String, Object> toolMap) {
		this.toolMap = toolMap;
	}

	/**
	 * 模板更新检查间隔时间（秒）
	 *
	 * @param updateDelaySeconds
	 */
	public void setUpdateDelaySeconds(Integer updateDelaySeconds) {
		this.updateDelaySeconds = updateDelaySeconds;
	}
}
